//
//  UdpServerUtil.m
//  TestTcpUdp
//
//  Created by leeson zhong on 2021/7/19.
//

#import "UdpServerUtil.h"
#import "GCDAsyncUdpSocket.h"

@interface UdpServerUtil()<GCDAsyncUdpSocketDelegate>{
    int serverPort;
    NSString *clientIp;
    int clientPort;
}

// 服务端socket
@property (strong, nonatomic) GCDAsyncUdpSocket *serverSocket;

@end

@implementation UdpServerUtil

-(BOOL)initWithServerPort:(int)port{
    // 初始化服务端socket
    self.serverSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
    NSError *error = nil;
    BOOL result = [self.serverSocket bindToPort:port error:&error];
    if (result == NO && self.delegate) {
        [self.serverSocket close];
        self.serverSocket = nil;
        [self.delegate onUdpServerClose];
    }else{
        serverPort = port;
        [self.serverSocket beginReceiving:&error];
    }
    return result;
}

-(BOOL)sendData:(NSData *)data{
    if (self.serverSocket && clientIp) {
        [self.serverSocket sendData:data toHost:clientIp port:clientPort withTimeout:-1 tag:0];
        return YES;
    }else{
        return NO;
    }
}

-(void)close{
    if (self.serverSocket) {
        [self.serverSocket close];
    }
}

-(int)getServerPort{
    return serverPort;
}
-(NSString *)getClientIp{
    return clientIp;
}
-(int)getClientPort{
    return clientPort;
}

#pragma GCDAsyncUdpSocketDelegate

/**
 * Called when the socket has received the requested datagram.
**/
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
                                             fromAddress:(NSData *)address
withFilterContext:(nullable id)filterContext{
    NSString *ip = [GCDAsyncUdpSocket hostFromAddress:address];
    int port = [GCDAsyncUdpSocket portFromAddress:address];
    
    if (clientIp && [clientIp isEqual:ip] && clientPort == port) {
        if (self.delegate) {
            [self.delegate onUdpServerReceiveData:data ClientIp:ip ClientPort:port];
        }
    }else{
        clientIp = ip;
        clientPort = port;
        if (self.delegate) {
            [self.delegate onUdpServerReceiveNewConnectionIp:ip Port:port];
            [self.delegate onUdpServerReceiveData:data ClientIp:ip ClientPort:port];
        }
    }
    
    
}

/**
 * Called when the socket is closed.
**/
- (void)udpSocketDidClose:(GCDAsyncUdpSocket *)sock withError:(NSError  * _Nullable)error{
    if (self.serverSocket) {
        self.serverSocket = nil;
        if (self.delegate) {
            [self.delegate onUdpServerClose];
        }
    }
}

@end
